#include "StdAfx.h"
#include "graphics/OpenGLWnd.h"
#include "graphics/GrVector.h"
#include "SgObject.h"
#include "RoundUpFactory.h"
#include "SgColor.h"
#include "SgBox.h"
#include "SgQuad.h"
#include "SgComposite.h"
#include "SgMaterial.h"
#include "SgPolygon.h"
#include "SgRegularPolygon.h"
#include "SgRegularCylinder.h"
#include "SgRotateAroundPoint.h"
#include "SgTranslate.h"
#include "SgTransform.h"
#include "SgMesh.h"
#include "AnimationRotateRoundUpSpin.h"
#include "AnimationRotateRoundUpLift.h"
#include "AnimationTranslateRoundUpButton.h"

const double PI = std::atan(1.0)*4;

CRoundUpFactory::CRoundUpFactory(void)
{
	m_root = NULL;
}

CRoundUpFactory::~CRoundUpFactory(void)
{
}

/*
 *		  Name: Create()
 * Description: Creates the round up ride
 *  Parameters: root - the root node of the scene graph to attach to
 */
void CRoundUpFactory::Create(CSgComposite *root)
{
	m_root = root;

	CSgPtr<CSgMaterial> rideMaterial = new CSgMaterial();
	rideMaterial->SetDiffuseColor(1.0f, 0.5f, 0.6f, 1.f);
	rideMaterial->SetSpecularColor(1.0f, 0.5f, 0.6f, 1.f);

	m_root->AddChild(rideMaterial);
	
	CSgPtr<CSgTranslate> rideMove = new CSgTranslate(-40, 0.5, -100+8);
	rideMaterial->AddChild(rideMove);


	// create the base of the ride (bottom of the cylinder)
	CSgPtr<CSgTranslate> spinningRaise = new CSgTranslate(0, 3, 0);


	// The rotation node for animating the spinning of the cylinder
	CSgPtr<CSgRotateAroundPoint> spin = new CSgRotateAroundPoint();
	spin->SetNormal(0, 1, 0);
	spin->SetPoint(0, 0, 0);
	spin->SetAngle(0);
	spin->AddChild(spinningRaise);

	CSgPtr<CAnimationRotateRoundUpSpin> animateSpin =
		new CAnimationRotateRoundUpSpin();
	animateSpin->SetNode(spin);
	m_timeline->AddChannel(animateSpin);


	// The rotation node for lifting the spin assembly
	CSgPtr<CSgRotateAroundPoint> spinLift = new CSgRotateAroundPoint();
	spinLift->SetAngle(0);
	spinLift->SetNormal(0, 0, 1);
	spinLift->SetPoint(25.5, 1.5, 0);
	rideMove->AddChild(spinLift);

	CSgPtr<CAnimationRotateRoundUpLift> animateLift =
		new CAnimationRotateRoundUpLift();
	animateLift->SetNode(spinLift);
	m_timeline->AddChannel(animateLift);


	spinLift->AddChild(spin);


	// create the floor of the spinning assembly
	CreateFloor(spinningRaise);
	// Create the base that will lift the spinning assembly
	CreateSpinningBase(spinLift);
	
	// Create the stationary base of the entire ride
	CreateBase(rideMove);

	// Make the sections of the outer cylinder, and the cables
	for(int angle = 0; angle < 38; angle++)
	{
		CSgPtr<CSgTranslate> transform = new CSgTranslate();
		// 18.4, 0, 0
		transform->SetProperties(18.4, 0, 0);

		spinningRaise->AddChild(transform);

		CSgPtr<CSgRotateAroundPoint> rotate = new CSgRotateAroundPoint();
		rotate->SetAngle(angle * 360.0 / 38);
		rotate->SetNormal(0, 1, 0);
		rotate->SetPoint(-18.4, 0, 0);
		transform->AddChild(rotate);

		// This creates two areas (three sections wide) for the entrance/exit
		if(!((angle >= 0 && angle <= 2) || (angle >= 19 && angle <= 21)))
		{	
			CSgPtr<CSgMaterial> sectionColor = new CSgMaterial();
			sectionColor->SetDiffuseColor(.9f, .9f, .9f, 1.f);
			sectionColor->SetSpecularColor(.9f, .9f, .9f, 1.f);
			rotate->AddChild(sectionColor);
			CreateCylinderSection(sectionColor);
			if(angle % 3 == 0)
			{
				// Draw the cable from the center cylinder to the outside wall
				CSgPtr<CSgRegularCylinder> cable = new CSgRegularCylinder();
				cable->SetProperties(10, 16.5, 0.1);
				CSgPtr<CSgTranslate> cableTransform = new CSgTranslate();
				cableTransform->SetProperties(9.5, -17.25, 0);

				CSgPtr<CSgRotateAroundPoint> cableRotate = new CSgRotateAroundPoint();
				cableRotate->SetAngle(85.65);
				cableRotate->SetNormal(0, 0, 1);
				cableRotate->SetPoint(-18.4, 7, 0);

				// Color rotate between red white and blue
				CSgPtr<CSgMaterial> cableColor = new CSgMaterial();
				switch((angle / 3) % 3)
				{
				case 0:
					cableColor->SetDiffuseColor(.87f, .08f, .16f, 1.f);
					cableColor->SetSpecularColor(.87f, .08f, .16f, 1.f);
					break;
				case 1:
					cableColor->SetDiffuseColor(.9f, .9f, .9f, 1.f);
					cableColor->SetSpecularColor(.9f, .9f, .9f, 1.f);
					break;
				case 2:
					cableColor->SetDiffuseColor(0.f, .32f, .64f, 1.f);
					cableColor->SetSpecularColor(0.f, .32f, .64f, 1.f);
					break;
				}
				rotate->AddChild(cableColor);
				
				cableColor->AddChild(cableTransform);
				cableTransform->AddChild(cableRotate);
				cableRotate->AddChild(cable);
			}
		}
		else if((angle == 0) || (angle == 19))
		{
			// Create the verticle pole to finish the cylinder sections on the end
			CSgPtr<CSgMaterial> gateColor = new CSgMaterial();
			gateColor->SetDiffuseColor(.9f, .9f, .9f, 1.f);
			gateColor->SetSpecularColor(.9f, .9f, .9f, 1.f);
			rotate->AddChild(gateColor);
			// Gate and back fence
			CSgPtr<CSgRegularCylinder> vertPole = new CSgRegularCylinder();
			vertPole->SetProperties(30, 7, .15);	
			CSgPtr<CSgTranslate> vertPoleMov = new CSgTranslate(-.7, .5, 1.5);
			vertPoleMov->AddChild(vertPole);
			gateColor->AddChild(vertPoleMov);
		}
		if(angle == 19)
		{
			// create the gated wall at one of the opens
			CSgPtr<CSgRegularCylinder> horzPole = new CSgRegularCylinder();
			horzPole->SetProperties(30, 8.7, .1);
			CSgPtr<CSgRotateAroundPoint> horzPoleTop = new CSgRotateAroundPoint();
			horzPoleTop->SetAngle(-90);
			horzPoleTop->SetNormal(1, 0, 0);
			horzPoleTop->SetPoint(0, 0, 0);
			horzPoleTop->AddChild(horzPole);
			CSgPtr<CSgRotateAroundPoint> horzPoleTopRot = new CSgRotateAroundPoint();
			horzPoleTopRot->SetAngle(9.47);
			horzPoleTopRot->SetNormal(0, 1, 0);
			horzPoleTopRot->SetPoint(0, 0, 0);
			horzPoleTopRot->AddChild(horzPoleTop);

			CSgPtr<CSgTranslate> horzPoleMidMov = new CSgTranslate(-.7, 3.675, 1.4);
			horzPoleMidMov->AddChild(horzPoleTopRot);
			CSgPtr<CSgTranslate> horzPoleBotMov = new CSgTranslate(-.7, 1.83, 1.4);
			horzPoleBotMov->AddChild(horzPoleTopRot);

			CSgPtr<CSgMaterial> backColor = new CSgMaterial();
			backColor->SetDiffuseColor(.9f, .9f, .9f, 1.f);
			backColor->SetSpecularColor(.9f, .9f, .9f, 1.f);
			rotate->AddChild(backColor);

			backColor->AddChild(horzPoleMidMov);
			backColor->AddChild(horzPoleBotMov);


		}
	
	}
	
	// Create the center cylinder that the cables will connect to
	CSgPtr<CSgMaterial> centerColor = new CSgMaterial();
	centerColor->SetDiffuseColor(.541f, .541f, 0.f, 1.f);
	centerColor->SetSpecularColor(.541f, .541f, 0.f, 1.f);
	spinningRaise->AddChild(centerColor);
	CreateCenterCylinder(centerColor);
}

/*
 *		  Name: CreateCylinderSection()
 * Description: Creates one section (seat) of the cylinder
 *  Parameters: parent - the parent scene graph node
 */
void CRoundUpFactory::CreateCylinderSection(CSgComposite *parent)
{
	double v[8][4] = {{0.5, 0, 1.5}, {0.5, 0, -1.5}, {-.5, 0, -1.5}, {-.5, 0, 1.5}, 
        {0.5, 7, 1.5}, {0.5, 7, -1.5}, {-.5, 7, -1.5}, {-.5, 7, 1.5}};
    double n[6][4] = {{0, 0, 1, 0}, {1, 0, 0, 0}, {0, 0, -1, 0}, 
	{-1, 0, 0, 0}, {0, 1, 0, 0}, {0, -1, 0, 0}};
	
	CSgPtr<CSgRegularCylinder> vertPole = new CSgRegularCylinder();
	vertPole->SetProperties(30, 7, .15);
	CSgPtr<CSgTranslate> vertPoleMov = new CSgTranslate(-.7, .5, 1.5);
	vertPoleMov->AddChild(vertPole);
	parent->AddChild(vertPoleMov);

	// Horzontal cross poles
	CSgPtr<CSgRegularCylinder> horzPole = new CSgRegularCylinder();
	horzPole->SetProperties(30, 2.7, .1);
	CSgPtr<CSgRotateAroundPoint> horzPoleTop = new CSgRotateAroundPoint();
	horzPoleTop->SetAngle(-90);
	horzPoleTop->SetNormal(1, 0, 0);
	horzPoleTop->SetPoint(0, 0, 0);
	horzPoleTop->AddChild(horzPole);

	CSgPtr<CSgTranslate> horzPoleTopMov = new CSgTranslate(-.7, 7.35, 1.4);
	horzPoleTopMov->AddChild(horzPoleTop);

	CSgPtr<CSgTranslate> horzPoleSecondMov = new CSgTranslate(-.7, 5.5, 1.4);
	horzPoleSecondMov->AddChild(horzPoleTop);
	CSgPtr<CSgTranslate> horzPoleThirdMov = new CSgTranslate(-.7, 3.675, 1.4);
	horzPoleThirdMov->AddChild(horzPoleTop);
	CSgPtr<CSgTranslate> horzPoleFourthMov = new CSgTranslate(-.7, 1.83, 1.4);
	horzPoleFourthMov->AddChild(horzPoleTop);

	// Back rest
	CSgPtr<CSgMaterial> backColor = new CSgMaterial();
	// .741 .254 .349
	backColor->SetDiffuseColor(.682f, .203f, .0f, 1.f);
	backColor->SetSpecularColor(.682f, .203f, .0f, 1.f);
	
	CSgPtr<CSgBox> backRest = new CSgBox(0.25, 4, 2);
	CSgPtr<CSgTranslate> backRestMov = new CSgTranslate(-.95, 2.75, 0);
	backRestMov->AddChild(backColor);
	backColor->AddChild(backRest);
	parent->AddChild(backRestMov);

	CSgPtr<CSgMaterial> poleColor = new CSgMaterial();
	poleColor->SetDiffuseColor(.9f, .9f, .9f, 1.f);
	poleColor->SetSpecularColor(.9f, .9f, .9f, 1.f);
	poleColor->AddChild(horzPoleTopMov);
	poleColor->AddChild(horzPoleSecondMov);
	poleColor->AddChild(horzPoleThirdMov);
	poleColor->AddChild(horzPoleFourthMov);

	parent->AddChild(poleColor);
}

/*
 *        Name: CreateFloor()
 * Description: Creates the floor of the ride, this both spins and raises up
 *  Parameters: parent - the parent scene graph node
 */
void CRoundUpFactory::CreateFloor(CSgComposite *parent)
{
	CSgPtr<CSgMaterial> floorMat = new CSgMaterial();
	floorMat->SetDiffuseColor(.7f, .7f, .7f, 1.f);
	floorMat->SetSpecularColor(.7f, .7f, .7f, 1.f);
	parent->AddChild(floorMat);


	CSgPtr<CSgMaterial> edgeColor = new CSgMaterial();
	edgeColor->SetDiffuseColor(.9f, .9f, .9f, 1.f);
	edgeColor->SetSpecularColor(.9f, .9f, .9f, 1.f);
	parent->AddChild(edgeColor);

	CSgPtr<CSgPolygon> floorBottom = new CSgPolygon();
	CSgPtr<CSgMesh> floorEdge = new CSgMesh();
	int numSides = 152;
	for (double i = 0; i < numSides; i++)
	{
		GLdouble start[] = {18*cos(i*2*PI/numSides+2*PI/(numSides*2.0)),0.0,18*sin(i*2*PI/numSides+2*PI/(numSides*2.0))};
		floorBottom->AddVertex3dv(start);
		floorBottom->AddNormal(CGrVector(0, -1, 0));
		floorBottom->AddTexCoord(CGrVector((cos(i * 2 * PI / numSides)/2) + 0.5, (sin(i * 2 * PI / numSides)/2) + 0.5, 1));

		floorEdge->AddVertex(CGrVector(start));


		GLdouble midNorm[] = {18*cos(i*2*PI/(numSides+.5)+2*PI/((numSides+.5)*2.0)),0.0,
			18*sin(i*2*PI/(numSides+.5)+2*PI/((numSides+.5)*2.0))};
		floorEdge->AddNormal(CGrVector(midNorm));

		// Only draw the outside edge of the floor rather then the vertical section
		//{0.5, 0, 1.5}, {0.5, 0, -1.5}, {-.5, 0, -1.5}, {-.5, 0, 1.5}


		/*CSgPtr<CSgPolygon> edge = new CSgPolygon();
		edge->AddNormal(CGrVector(1, 0, 0));
		edge->AddVertex3d(-0.5, 0, 1.5);
		edge->AddNormal(CGrVector(1, 0, 0));
		edge->AddVertex3d(-0.5, 0, -1.5);
		edge->AddNormal(CGrVector(1, 0, 0));
		edge->AddVertex3d(-0.5, .5, -1.5);

		edge->AddNormal(CGrVector(1, 0, 0));
		edge->AddVertex3d(-0.5, .5, 1.5);
		parent->AddChild(edgeColor);
		edgeColor->AddChild(edge);*/



	}
	for (double i = 0; i < numSides; i++)
	{
		GLdouble topstart[] = {18*cos(i*2*PI/numSides+2*PI/(numSides*2.0)),0.5,18*sin(i*2*PI/numSides+2*PI/(numSides*2.0))};
		floorEdge->AddVertex(CGrVector(topstart));
	}
	for(int i = 0; i < numSides; i++)
	{
		floorEdge->AddFlatQuad( (i+1)%numSides, i, (i%numSides)+numSides, ((i+1)%numSides)+numSides, i);
	}

	edgeColor->AddChild(floorEdge);

	CSgPtr<CSgRotateAroundPoint> floorTopRotate = new CSgRotateAroundPoint();
	floorTopRotate->SetAngle(180);
	floorTopRotate->SetNormal(CGrVector(1, 0, 0));
	floorTopRotate->SetPoint(CGrVector(0, 0, 0));
	floorTopRotate->AddChild(floorBottom);


	CSgPtr<CSgTranslate> floorTopTrans = new CSgTranslate(0, 0.5, 0);
	floorTopTrans->AddChild(floorTopRotate);

	CSgPtr<CSgTexture> floorTopTex = new CSgTexture(L"roundupfloor.bmp");
	floorTopTex->AddChild(floorTopTrans);

	floorMat->AddChild(floorTopTex);
	floorMat->AddChild(floorBottom);
}

/*
 *        Name: CreateBase()
 * Description: Creates the base of the ride.  completely stationary
 *  Parameters: parent - the parent scene graph node
 */
void CRoundUpFactory::CreateBase(CSgComposite *parent)
{
	CSgPtr<CSgMaterial> iron = new CSgMaterial();
	iron->SetDiffuseColor(.26f, .27f, .29f, 1.f);
	iron->SetSpecularColor(.26f, .27f, .29f, 1.f);
	parent->AddChild(iron);

	// Left Outrigger
	CSgPtr<CSgTranslate> leftOutrigTrans = new CSgTranslate();
	leftOutrigTrans->SetProperties(-6.5, 0.5, 9.5);
	iron->AddChild(leftOutrigTrans);

	CSgPtr<CSgRotateAroundPoint> leftOutrigRot = new CSgRotateAroundPoint();
	leftOutrigRot->SetAngle(10);
	leftOutrigRot->SetNormal(0, 1, 0);
	leftOutrigRot->SetPoint(6.5, -0.5, -9.5);
	leftOutrigTrans->AddChild(leftOutrigRot);
	CreateIBeam(leftOutrigRot, 35);


	// Right Outrigger
	CSgPtr<CSgTranslate> rightOutrigTrans = new CSgTranslate();
	rightOutrigTrans->SetProperties(-6.5, 0.5, -9.5);
	iron->AddChild(rightOutrigTrans);

	CSgPtr<CSgRotateAroundPoint> rightOutrigRot = new CSgRotateAroundPoint();
	rightOutrigRot->SetAngle(-10);
	rightOutrigRot->SetNormal(0, 1, 0);
	rightOutrigRot->SetPoint(6.5, -0.5, 9.5);
	rightOutrigTrans->AddChild(rightOutrigRot);
	CreateIBeam(rightOutrigRot, 35);

	// Left and Right Outrigger stands
	CreateBaseStand(parent, -2, 0, -9);
	CreateBaseStand(parent, -2, 0, 9);
	CreateBaseStand(parent, 23.5, 0, -4.5);
	CreateBaseStand(parent, 23.5, 0, 4.5);


	CSgPtr<CSgMaterial> concreteColor = new CSgMaterial();
	concreteColor->SetDiffuseColor(.9f, .9f, .9f, 1.f);
	concreteColor->SetSpecularColor(.9f, .9f, .9f, 1.f);

	CSgPtr<CSgTexture> concrete = new CSgTexture(L"concrete01.bmp");
	parent->AddChild(concreteColor);
	concreteColor->AddChild(concrete);

	// Entrance and Exit steps
	CSgPtr<CSgBox> Step = new CSgBox(8, 0.5, 2.25);
	CSgPtr<CSgTranslate> topStepMove = new CSgTranslate(20, 2.5, 4.8625);
	topStepMove->AddChild(Step);
	concrete->AddChild(topStepMove);

	CSgPtr<CSgBox>secondStep = new CSgBox(8, 0.6, 2);
	CSgPtr<CSgTranslate> secondStepMove = new CSgTranslate(20, 2, 7);
	secondStepMove->AddChild(secondStep);
	concrete->AddChild(secondStepMove);


	// Second platform (stationary)
	CSgPtr<CSgBox> platform = new CSgBox(8, 2.5, 6);
	CSgPtr<CSgTranslate> platformMove = new CSgTranslate(20, -.5, 11);
	platformMove->AddChild(platform);
	concrete->AddChild(platformMove);


	CSgPtr<CSgBox> thirdStep = new CSgBox(2, 1.833, 6);
	CSgPtr<CSgTranslate> thirdStepMove = new CSgTranslate(28, -.5, 11);
	thirdStepMove->AddChild(thirdStep);
	concrete->AddChild(thirdStepMove);

	CSgPtr<CSgBox> fourthStep = new CSgBox(2, 1.166, 6);
	CSgPtr<CSgTranslate> fourthStepMove = new CSgTranslate(30, -.5, 11);
	fourthStepMove->AddChild(fourthStep);
	concrete->AddChild(fourthStepMove);

	CSgPtr<CSgBox> fifthStep = new CSgBox(2, .55, 6);
	CSgPtr<CSgTranslate> fifthStepMove = new CSgTranslate(32, -.5, 11);
	fifthStepMove->AddChild(fifthStep);
	concrete->AddChild(fifthStepMove);





	// Add the railings
	/*CSgPtr<CSgMaterial> railingColor = new CSgMaterial();
	railingColor->SetDiffuseColor(1.f, 1.f, 1.f, 1.f);
	railingColor->SetSpecularColor(1.f, 1.f, 1.f, 1.f);
	parent->AddChild(railingColor);

	// Outside vertical poles for railings
	CSgPtr<CSgRegularCylinder> vertRailing = new CSgRegularCylinder();
	vertRailing->SetProperties(20, 3, 0.1);
	CSgPtr<CSgTranslate> vert1 = new CSgTranslate(20.1, 3, 4.8625);
	vert1->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert2 = new CSgTranslate(20.1, 2.6, 7);
	vert2->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert3 = new CSgTranslate(20.1, 2, 9);
	vert3->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert4 = new CSgTranslate(20.1, 2, 11);
	vert4->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert5 = new CSgTranslate(20.1, 2, 13.9);
	vert5->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert6 = new CSgTranslate(23, 2, 13.9);
	vert6->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert7 = new CSgTranslate(26, 2, 13.9);
	vert7->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert8 = new CSgTranslate(29, 1.333, 13.9);
	vert8->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert9 = new CSgTranslate(31, .666, 13.9);
	vert9->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert10 = new CSgTranslate(33, .05, 13.9);
	vert10->AddChild(vertRailing);
	
	// Inside vertical poles for railings
	CSgPtr<CSgTranslate> vert11 = new CSgTranslate(27.9, 3, 4.8625);
	vert11->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert12 = new CSgTranslate(27.9, 2.6, 7);
	vert12->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert13 = new CSgTranslate(27.9, 2, 8.1);
	vert13->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert14 = new CSgTranslate(31, .05, 8.1);
	vert14->AddChild(vertRailing);
	CSgPtr<CSgTranslate> vert15 = new CSgTranslate(33, .05, 8.1);
	vert15->AddChild(vertRailing);

	railingColor->AddChild(vert1);
	railingColor->AddChild(vert2);
	railingColor->AddChild(vert3);
	railingColor->AddChild(vert4);
	railingColor->AddChild(vert5);
	railingColor->AddChild(vert6);
	railingColor->AddChild(vert7);
	railingColor->AddChild(vert8);
	railingColor->AddChild(vert9);
	railingColor->AddChild(vert10);
	railingColor->AddChild(vert11);
	railingColor->AddChild(vert12);
	railingColor->AddChild(vert13);
	railingColor->AddChild(vert14);
	railingColor->AddChild(vert15);*/




	// Operator's Podium
	
	CSgPtr<CSgMaterial> podColor = new CSgMaterial();
	podColor->SetDiffuseColor(.5f, .5f, .5f, 1.f);
	podColor->SetSpecularColor(.5f, .5f, .5f, 1.f);	
	parent->AddChild(podColor);

	CSgPtr<CSgBox> podiumBase = new CSgBox(2, 4, 0.75);
	CSgPtr<CSgTranslate> podiumBaseMov = new CSgTranslate(20, 2, 11.5);
	podiumBaseMov->AddChild(podiumBase);
	podColor->AddChild(podiumBaseMov);
	
	double podTop[6][4] = {{0, 0, .75, 1}, {2, 0, .75, 1}, {2, 0, 0, 1}, {0, 0, 0, 1},
	{2, .75, 0, 1}, {0, .75, 0, 1}};
	double podTopNorm[5][4] = {{0, -1, 0, 1}, {1, 0, 0, 1}, {0, 0, -1, 1}, {-1, 0, 0, 1}, {0, .707, .707, 1}};
	CSgPtr<CSgPolygon> podiumTop = new CSgPolygon();
	podiumTop->AddTexCoord(CGrVector(0, 0, 1, 1));
	podiumTop->AddVertex3dv(podTop[0]);
	podiumTop->AddTexCoord(CGrVector(1, 0, 1, 1));
	podiumTop->AddVertex3dv(podTop[1]);
	podiumTop->AddTexCoord(CGrVector(1, 0.55, 1, 1));
	podiumTop->AddVertex3dv(podTop[4]);
	podiumTop->AddTexCoord(CGrVector(0 ,0.55, 1, 1));
	podiumTop->AddVertex3dv(podTop[5]);
	podiumTop->AddNormal(CGrVector(podTopNorm[4]));


	CSgPtr<CSgTexture> podControl = new CSgTexture(L"ControlPanel.bmp");
	podControl->AddChild(podiumTop);

	CSgPtr<CSgPolygon> podiumTopLSide = new CSgPolygon();
	podiumTopLSide->AddVertex3dv(podTop[1]);
	podiumTopLSide->AddVertex3dv(podTop[2]);
	podiumTopLSide->AddVertex3dv(podTop[4]);
	podiumTopLSide->AddNormal(CGrVector(podTopNorm[1]));

	CSgPtr<CSgPolygon> podiumTopRSide = new CSgPolygon();
	podiumTopRSide->AddVertex3dv(podTop[5]);
	podiumTopRSide->AddVertex3dv(podTop[3]);
	podiumTopRSide->AddVertex3dv(podTop[0]);
	podiumTopRSide->AddNormal(CGrVector(podTopNorm[3]));

	CSgPtr<CSgPolygon> podiumTopBot = new CSgPolygon();
	podiumTopBot->AddVertex3dv(podTop[3]);
	podiumTopBot->AddVertex3dv(podTop[2]);
	podiumTopBot->AddVertex3dv(podTop[1]);
	podiumTopBot->AddVertex3dv(podTop[0]);
	podiumTopBot->AddNormal(CGrVector(podTopNorm[0]));


	CSgPtr<CSgRegularCylinder> podiumTopButton = new CSgRegularCylinder();
	podiumTopButton->SetProperties(20, .2, .2);
	CSgRotateAroundPoint *buttonRot = new CSgRotateAroundPoint();
	buttonRot->SetAngle(45);
	buttonRot->SetNormal(1, 0, 0);
	buttonRot->SetPoint(0, 0, 0);
	CSgPtr<CSgMaterial> buttonColor = new CSgMaterial();
	buttonColor->SetDiffuseColor(.5f, 0.f, .03f, 1.f);
	buttonColor->SetSpecularColor(.5f, 0.f, .03f, 1.f);
	buttonColor->AddChild(podiumTopButton);

	CSgPtr<CSgTranslate> buttonMov = new CSgTranslate(1, .375, .375);
	buttonMov->AddChild(buttonRot);

	CSgPtr<CSgTranslate> buttonAnimMov = new CSgTranslate(0, 0, 0);
	buttonRot->AddChild(buttonAnimMov);
	buttonAnimMov->AddChild(buttonColor);

	CSgPtr<CAnimationTranslateRoundUpButton> buttonAnim = new CAnimationTranslateRoundUpButton();
	buttonAnim->SetNode(buttonMov);
	m_timeline->AddChannel(buttonAnim);


	CSgPtr<CSgTranslate> podBaseTopMov = new CSgTranslate(0, 3.25, 0.375);
	podBaseTopMov->AddChild(podControl);
	podBaseTopMov->AddChild(podiumTopLSide);
	podBaseTopMov->AddChild(podiumTopRSide);
	podBaseTopMov->AddChild(podiumTopBot);
	podBaseTopMov->AddChild(buttonMov);

	podiumBaseMov->AddChild(podBaseTopMov);



}

/*
 *        Name: CreateIBeam()
 * Description: Creates an I-Beam, consisting of three rectangular prisms
 *  Parameters: parent - the parent scene graph node
 *			    length - the length of the beam
 */
void CRoundUpFactory::CreateIBeam(CSgComposite *parent, double length)
{

	CSgPtr<CSgTexture> iron = new CSgTexture(L"Iron.bmp");
	parent->AddChild(iron);

	double top[8][4] = {{0, 1.75, -0.5, 1}, {0, 1.75, 0.5, 1}, {length, 1.75, 0.5, 1}, {length, 1.75, -0.5, 1},
		{0, 2, -0.5, 1}, {0, 2, 0.5, 1}, {length, 2, 0.5, 1}, {length, 2, -0.5, 1}};
	double mid[8][4] = {{0, 0.25, -.1, 1}, {0, 0.25, 0.1, 1}, {length, 0.25, 0.1, 1}, {length, 0.25, -0.1, 1},
		{0, 1.75, -.1, 1}, {0, 1.75, 0.1, 1}, {length, 1.75, 0.1, 1}, {length, 1.75, -0.1, 1}};
	double bot[8][4] = {{0, 0, -0.5, 1}, {0, 0, 0.5, 1}, {length, 0, 0.5, 1}, {length, 0, -0.5, 1},
		{0, 0.25, -0.5, 1}, {0, 0.25, 0.5, 1}, {length, 0.25, 0.5, 1}, {length, 0.25, -0.5, 1}};
	CGrVector normals[6] = {CGrVector(1, 0, 0, 1), CGrVector(0, 1, 0, 1), CGrVector(0, 0, 1, 1),
		CGrVector(-1, 0, 0, 1), CGrVector(0, -1, 0, 1), CGrVector(0, 0, -1, 1)};
	
	CSgPtr<CSgBox> bottomBox = new CSgBox(length, .25, 1);
	CSgPtr<CSgTranslate> topBox = new CSgTranslate(0, 1.75, 0);
	topBox->AddChild(bottomBox);
	CSgPtr<CSgBox> midBox = new CSgBox(length, 1.5, .2);
	CSgPtr<CSgTranslate> midMove = new CSgTranslate(0, 0.25, 0);
	midMove->AddChild(midBox);

	iron->AddChild(bottomBox);
	iron->AddChild(midMove);
	iron->AddChild(topBox);
}


/*
 *        Name: CreateBaseStand()
 * Description: Creates the support stand that holds up an IBeam
 *  Parameters: parent - the parent scene graph node
 *			    x,y,z - The location of the base stand
 */
void CRoundUpFactory::CreateBaseStand(CSgComposite *parent, double x, double y, double z)
{
	CSgPtr<CSgMaterial> iron = new CSgMaterial();
	iron->SetDiffuseColor(.2f, .21f, .23f, 1.f);
	iron->SetSpecularColor(.2f, .21f, .23f, 1.f);
	parent->AddChild(iron);

	// Outrigger stand
	CSgPtr<CSgRegularCylinder> ROutrigStand = new CSgRegularCylinder();
	ROutrigStand->SetProperties(20, 2.5, 0.5);
	CSgPtr<CSgTranslate> ROutrigStandTrans = new CSgTranslate();
	ROutrigStandTrans->SetProperties(x, y + 2.5, z);
	CSgPtr<CSgRotateAroundPoint> ROutrigStandRot = new CSgRotateAroundPoint();
	ROutrigStandRot->SetAngle(180);
	ROutrigStandRot->SetNormal(1, 0, 0);
	ROutrigStandRot->SetPoint(0, 0, 0);
	ROutrigStandTrans->AddChild(ROutrigStandRot);
	ROutrigStandRot->AddChild(ROutrigStand);
	iron->AddChild(ROutrigStandTrans);


	CSgPtr<CSgMaterial> rubber = new CSgMaterial();
	rubber->SetDiffuseColor(.06f, .07f, .09f, 1.f);
	rubber->SetSpecularColor(.06f, .07f, .09f, 1.f);
	parent->AddChild(rubber);

	// Outrigger stand base
	CSgPtr<CSgRegularCylinder> ROutrigBase = new CSgRegularCylinder();
	ROutrigBase->SetProperties(20, 0.5, 1);
	CSgPtr<CSgTranslate> ROutrigBaseTrans = new CSgTranslate();
	ROutrigBaseTrans->SetProperties(x, y, z);
	CSgPtr<CSgRotateAroundPoint> ROutrigBaseRot = new CSgRotateAroundPoint();
	ROutrigBaseRot->SetAngle(180);
	ROutrigBaseRot->SetNormal(1, 0, 0);
	ROutrigBaseRot->SetPoint(0, 0, 0);
	ROutrigBaseTrans->AddChild(ROutrigBaseRot);
	ROutrigBaseRot->AddChild(ROutrigBase);
	rubber->AddChild(ROutrigBaseTrans);	


}


/*
 *        Name: CreateSpinningBase()
 * Description: Creates the base of the spinning portion of the ride.
 *				All of this will raise up, but will not spin with the ride
 *  Parameters: parent - the parent scene graph node
 */
void CRoundUpFactory::CreateSpinningBase(CSgComposite *parent)
{
	//.26 .27 .29
	CSgPtr<CSgMaterial> iron = new CSgMaterial();
	iron->SetDiffuseColor(.26f, .27f, .29f, 1.f);
	iron->SetSpecularColor(.26f, .27f, .29f, 1.f);


	parent->AddChild(iron);
	// Left support beam
	CSgPtr<CSgTranslate> leftIBeamTrans = new CSgTranslate();
	leftIBeamTrans->SetProperties(-3, 0.5, 3);
	iron->AddChild(leftIBeamTrans);
	CreateIBeam(leftIBeamTrans, 30);

	// Right support beam
	CSgPtr<CSgTranslate> rightIBeamTrans = new CSgTranslate();
	rightIBeamTrans->SetProperties(-3, 0.5, -3);
	iron->AddChild(rightIBeamTrans);
	CreateIBeam(rightIBeamTrans, 30);

	// Axle
	CSgPtr<CSgRegularCylinder> axle = new CSgRegularCylinder();
	axle->SetProperties(30, 12, .5);

	CSgPtr<CSgTranslate> axleTrans = new CSgTranslate();
	axleTrans->SetProperties(25.5, 1.5, -6);
	iron->AddChild(axleTrans);

	CSgPtr<CSgRotateAroundPoint> axleRot = new CSgRotateAroundPoint();
	axleRot->SetAngle(90);
	axleRot->SetNormal(1, 0, 0);
	axleRot->SetPoint(0, 0, 0);


	axleTrans->AddChild(axleRot);
	axleRot->AddChild(axle);


	// Rotation washer
	CSgPtr<CSgRegularCylinder> washer = new CSgRegularCylinder();
	washer->SetProperties(20, .5, 8);

	CSgPtr<CSgTranslate> washerTrans = new CSgTranslate();
	washerTrans->SetProperties(0, 2.5, 0);
	washerTrans->AddChild(washer);

	iron->AddChild(washerTrans);

	// entrance/exit platform
	CSgPtr<CSgMaterial> wood = new CSgMaterial();
	wood->SetDiffuseColor(1.f, 1.f, 1.f, 1.f);
	wood->SetSpecularColor(1.f, 1.f, 1.f, 1.f);

	CSgPtr<CSgTexture> woodTex = new CSgTexture(L"bwood.bmp");
	wood->AddChild(woodTex);
	
	parent->AddChild(wood);

	CSgPtr<CSgTranslate> platformMov = new CSgTranslate();
	platformMov->SetProperties(18.5, 2.5, 0);
	woodTex->AddChild(platformMov);
	
	CSgPtr<CSgBox> platform = new CSgBox(9.5, 1, 7);
	platformMov->AddChild(platform);
}



void CRoundUpFactory::CreateCenterCylinder(CSgComposite *parent)
{
	// Bottom radius of 1, expands out to 2 at height 9,
	// then curls back into a point, like an upside down funnel
	CSgPtr<CSgMesh> meshCylinder = new CSgMesh();
	
	for(int i=0; i<76; i++)
	{
		meshCylinder->AddVertex(CGrVector(cos(i * PI / 38), 0, sin(i * PI / 38)));
		CGrVector bottomHalfNorm(2 * cos((i + (1/152)) * PI / 38), -1.0 / 9, 2 * sin((i + (1/152)) * PI / 38));
		bottomHalfNorm.Normalize3();
		meshCylinder->AddNormal(bottomHalfNorm);
	}
	for(int i=0; i<76; i++)
	{
		meshCylinder->AddVertex(CGrVector(2 * cos(i * PI / 38), 9, 2 * sin(i * PI / 38)));
		meshCylinder->AddNormal(CGrVector(0, 1, 0));
	}
	for(int i=0; i<75; i++)
	{
		meshCylinder->AddFlatQuad(i+1, i, i+76, i+77, i);
	}
	meshCylinder->AddFlatQuad(0, 75, 151, 76, 75);


	// Cone at the top
	// from radius 2 down to a point at height of +3
	CSgPtr<CSgMesh> meshCone = new CSgMesh();
	for(int i=0; i<76; i++)
	{
		meshCone->AddVertex(CGrVector(2 * cos(i * PI / 38), 9, 2 * sin(i * PI / 38)));
		meshCone->AddNormal(CGrVector(2 * cos(i * PI / 38), 3/9.0, 2 * sin(i * PI / 38)));
	}
	meshCone->AddVertex(CGrVector(0, 12, 0));

	for(int i=0; i<75; i++)
	{
		meshCone->AddFlatTriangle(i+1, i, 76, i);
	}
	meshCone->AddFlatTriangle(0, 75, 76, 75);

	parent->AddChild(meshCylinder);
	parent->AddChild(meshCone);
}